/**
 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// NOLINTNEXTLINE(misc-definitions-in-headers,readability-function-size)
inline void AdjustFlags([[maybe_unused]] RuntimeInterface::IntrinsicId intrinsic, [[maybe_unused]] Inst *inst)
{
    // Note: code relies on current intrinsic instruction default flags
% if Compiler::intrinsics.any? {|intrinsic| !intrinsic.clear_flags.empty? or !intrinsic.set_flags.empty?}
    switch (intrinsic)
    {
% Compiler::intrinsics.select {|intrinsic| !intrinsic.clear_flags.empty? or !intrinsic.set_flags.empty?}.each do |intrinsic|
    case RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>:
    {
        constexpr auto CLEAR_FLAGS = <%= intrinsic.clear_flags.empty? ? "0U" : intrinsic.clear_flags.collect { |f| "compiler::inst_flags::" + f.upcase }.join("|") %>;
        constexpr auto SET_FLAGS = <%= intrinsic.set_flags.empty? ? "0U" : intrinsic.set_flags.collect { |f| "compiler::inst_flags::" + f.upcase }.join("|") %>;
        static_assert((SET_FLAGS & CLEAR_FLAGS) == 0, "<%= intrinsic.enum_name %> CLEAR_FLAGS cannot intersect SET_FLAGS");
% if !intrinsic.clear_flags.empty?
        inst->ClearFlag(static_cast<inst_flags::Flags>(CLEAR_FLAGS));
% end
% if !intrinsic.set_flags.empty?
        static_assert((SET_FLAGS & compiler::inst_flags::CAN_THROW) == 0 || (CLEAR_FLAGS & (compiler::inst_flags::REQUIRE_STATE | compiler::inst_flags::RUNTIME_CALL)) == 0, "<%= intrinsic.enum_name %> cannot set can_throw flag");
        inst->SetFlag(static_cast<inst_flags::Flags>(SET_FLAGS));
% end
        break;
    }
% end
#if defined(ENABLE_LIBABCKIT)
#include "dyn_intrinsics_flags.inc"
#endif
    default:
        return;
    }
% end
}

inline bool IsIrtocIntrinsic(RuntimeInterface::IntrinsicId intrinsic)
{
    switch (intrinsic)
    {
% Compiler::intrinsics.select(&:is_irtoc?).each do |intrinsic|
    case RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>:
% end
        return true;
    default:
        return false;
    }
}

inline bool IsFastpathIntrinsic(RuntimeInterface::IntrinsicId intrinsic)
{
    switch (intrinsic)  // NOLINT(hicpp-multiway-paths-covered)
    {
% Compiler::intrinsics.select(&:is_fastpath).each do |intrinsic|
    case RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>:
        return true;
% end
    default:
        return false;
    }
}

inline bool IsStackRangeIntrinsic(RuntimeInterface::IntrinsicId intrinsic, [[maybe_unused]] size_t *explicitArgs)
{
    switch (intrinsic) {  // NOLINT(hicpp-multiway-paths-covered)
% Compiler::intrinsics.select(&:is_stackrange?).each do |intrinsic|
    case RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>:
        *explicitArgs = <%= intrinsic.arguments.length() - 1 %>;
        return true;
% end
    default:
        return false;
    }
}

// Returns true if intrinsic is not a native call, but parameters are passed
// like in native calling convention
inline bool IntrinsicNeedsParamLocations([[maybe_unused]] RuntimeInterface::IntrinsicId intrinsic)
{
% if Compiler::intrinsics.any?(&:need_param_locations)
    // NOLINTNEXTLINE(hicpp-multiway-paths-covered)
    switch (intrinsic)
    {
% Compiler::intrinsics.select(&:need_param_locations).each do |intrinsic|
    case RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>:
% end
        return true;
    default:
        return false;
    }
% else
    return false;
% end
}

inline bool IsIntrinsicInlinedByInputTypes([[maybe_unused]] RuntimeInterface::IntrinsicId intrinsic)
{
% list = Compiler::intrinsics.select {|intrinsic| intrinsic.respond_to?(:inline_func) && intrinsic.inline_need_types}
% unless list.empty?
    // NOLINTNEXTLINE(hicpp-multiway-paths-covered)
    switch (intrinsic)
    {
% list.each do |intrinsic|
    case RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>:
% end
        return true;
    default:
        return false;
    }
% else
    return false;
% end
}

